# -*- coding:utf-8 -*- #

from twisted.internet.protocol import Factory,Protocol,ClientCreator
from twisted.internet.reactor import callLater
from twisted.internet.task import LoopingCall

#使工作线程>512
#import os
#if os.name!='nt':
    #from twisted.internet import epollreactor
    #epollreactor.install()    
#else:
    #from twisted.internet import iocpreactor
    #iocpreactor.install()
    
from twisted.internet import reactor,defer,threads
from twisted.python import log
from twisted.python.logfile import DailyLogFile

from twisted.protocols import basic
from twisted.protocols.basic import LineReceiver
from twisted.internet.error import CannotListenError


import sys
import subprocess

import socket
import fcntl
import struct
import os

 
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])


'''
shell命令调用块
'''
def mypopen(cmd):
    return subprocess.Popen(cmd, shell=True, close_fds=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


class RsyncServer(LineReceiver):
    """
    同步
    /usr/bin/rsync -vzrtopg --progress --delete root@192.168.168.10::game_boss /data/www/game_boss
    """
    def __init__(self):
        self.recvBuf = ""
        self.client = ""
        #分割参数
        self.split = "$sftang"
        
    #发送文本格式数据
    def sendData(self,data):
        self.transport.write(data)

    #连接断开时候发生
    def connectionLost(self, reason):
        #客户端端口后调用 ＃主动踢掉client通过sendError进行
        #print("OutUser : %s"%(self.transport.getPeer()))
        pass
        

    #新客户端进入
    def connectionMade(self):
        #连接客户端的ip地址
        selfip = self.transport.getPeer().host
        self.client = selfip
        print("NewClient : %s"%(self.transport.getPeer()))

    #接收数据
    def dataReceived(self, data):
        
        #同步模块
        rsync_module = data.split(self.split)[0]
        #本地目录
        rsync_dir = data.split(self.split)[1]
        #忽略文件或目录
        rsync_exclude = data.split(self.split)[2]
        #执行命令
        command = data.split(self.split)[3]
        
        #建立同步目录
        if not os.path.isdir(rsync_dir):
            os.makedirs(rsync_dir)
            
        #获取主机名反接的ip
        try:
            localip = get_ip_address('eth0')
        except:
            localip = socket.gethostbyname(socket.gethostname())
            
        hname = socket.gethostname()
        
        #解决rsync切换目录错误问题
        #stderrdata--> shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
        os.chdir('/tmp')
        #检查是否有排除文件
        if rsync_exclude == '':

            rsync_cmd="/usr/bin/rsync -vzrtopg --progress --delete root@%s::%s %s" % (self.client,
                                                                                      rsync_module,
                                                                                      rsync_dir
                                                                                      )

        else:
            #检查是否第一次同步,标准：目录下无文件
            if len(os.listdir(rsync_dir)) == 0:
                
                #第一次同步不进行过滤操作
                rsync_cmd="/usr/bin/rsync -vzrtopg --progress --delete root@%s::%s %s" % (self.client,
                                                                                          rsync_module,
                                                                                          rsync_dir
                                                                                          )
            else:
                exclude = []
                for i in rsync_exclude.split(' '):
                    exclude.append("--exclude=" + i)
                    
                rsync_cmd="/usr/bin/rsync -vzrtopg --progress --delete %s root@%s::%s %s" % (" ".join(exclude),
                                                                                             self.client,
                                                                                             rsync_module,
                                                                                             rsync_dir
                                                                                             )
                   
        print "rsync_cmd===>",rsync_cmd
        stdoutdata, stderrdata = mypopen(rsync_cmd).communicate()

        if len(stderrdata) != 0:
            print "stderrdata-->",stderrdata
            rsync_log = "\033[31;1m%s--%s-----rsync-error\033[0m\n" % (hname,localip)
            
        else:
            rsync_log = "%s--%s-----rsync-ok\n" % (hname,localip)
            print "command===>",command
            #同步成功后，执行对应的操作命令
            if command == '':
                #没有命令执行
                rsync_log = rsync_log + \
                    "%s--%s-----没有接到执行命令-ok\n" % (hname,localip)
            else:

                #执行命令
                stdoutdata, stderrdata = mypopen(command).communicate()
                
                if len(stderrdata) != 0:
                    print "stderrdata-->",stderrdata
                    rsync_log = rsync_log + "\033[31;1m%s--%s-----命令执行失败:%s\033[0m\n" % (hname,
                                                                                                localip,
                                                                                                stderrdata
                                                                                                )
                    
                else:
                    rsync_log = rsync_log + "%s--%s-----命令执行成功:%s\n" % (hname,localip,stdoutdata)
                        

        print "rsync_log===>",rsync_log
        self.sendData(rsync_log)
        
    
class RsyncServerFactory(Factory):
    protocol = RsyncServer
    
if __name__ == '__main__':
    
    #获取程序所在的全路径目录
    BASEDIR = os.path.abspath(os.path.dirname(__file__))
    #提示fromFullPath不存在，使用下面的方法
    #logfile = os.path.join(BASEDIR,'logs/rsync.log',)
    #log.startLogging(DailyLogFile.fromFullPath(logfile))
    
    logdir = os.path.join(BASEDIR,'log',)
    if not os.path.isdir(logdir):
        os.makedirs(logdir)
        
    log.startLogging(DailyLogFile('rsync.log',logdir))
        
    listen_port = 28000
    
    try:
        print "启动同步客户端"
        reactor.listenTCP(listen_port, RsyncServerFactory())
        print ("\033[32;1mRunning Socket on %s:%s\033[0m" % ("", str(listen_port)))
    except CannotListenError:
        print ("\033[31;1mSocket %s  Address already in use.\033[0m" % str(listen_port))
        sys.exit()

    reactor.run()
